home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Graphics / GraphicsWorkshop / Source / Converters / ppm.m < prev    next >
Encoding:
Text File  |  1992-05-27  |  9.5 KB  |  419 lines

  1. #import <stdio.h>
  2. #import <math.h>
  3. #import <strings.h>
  4. #import <stdlib.h>
  5. #import <streams/streams.h>
  6. #import <appkit/graphics.h>
  7. #import <appkit/NXBitmapImageRep.h>
  8. #import <appkit/color.h>
  9. #import "ppm.h"
  10. #import "NXBitmapImageRepControl.h"
  11. #import "ImageControl.h"
  12.  
  13. @implementation PPM
  14.  
  15.     NXStream        *myStream;
  16.     unsigned char        *data[5];
  17.     char                type[5];
  18.     int                width, height, levels;
  19.     int                bits;
  20.     int                cwid;
  21.     int                iwid;
  22.     int                padBits;
  23.  
  24. - init
  25. {
  26.     iwid = sizeof(int) * 8;
  27.     cwid = sizeof(char) * 8;
  28.  
  29.     return self;
  30. }
  31.  
  32. - free
  33. {
  34.     return self;
  35. }
  36.  
  37. - killToEOL
  38. {
  39.     while (NXGetc(myStream) != '\n') ;
  40.     return self;
  41. }
  42.  
  43. - getString: (char *)str from: (NXStream *)stream
  44. {
  45.     char        buffer[256];
  46.     
  47.     do {
  48.         NXScanf(stream, "%s", str);
  49.         if (str[0] == '#') {
  50.             NXScanf(stream, "%[^\n]", buffer); (void)NXGetc(stream);
  51.         }
  52.     } while (str[0] == '#');
  53.  
  54.     return self;
  55. }
  56.  
  57. - (int)getIntFrom: (NXStream *)stream
  58. {
  59.     char        buffer[256];
  60.     
  61.     do {
  62.         NXScanf(stream, "%s", buffer);
  63.         if (buffer[0] == '#') {
  64.             NXScanf(stream, "%[^\n]", buffer); (void)NXGetc(stream);
  65.         }
  66.         else break;
  67.     } while (1);
  68.     return(atoi(buffer));
  69. }
  70.  
  71. - (BOOL)readRawFromStream
  72. {
  73.     int                x, y, shift, curInt;
  74.     unsigned int        c[3];
  75.     unsigned int        *dataII[3];
  76.     
  77.     dataII[0] = (unsigned int *)data[0];
  78.     dataII[1] = (unsigned int *)data[1];
  79.     dataII[2] = (unsigned int *)data[2];
  80.  
  81. #ifdef DEBUG
  82.     fprintf(stderr, "Okay, we're off and reading raw data\n");
  83. #endif
  84.  
  85.     [self killToEOL];
  86.  
  87.     shift = 0;
  88.     dataII[0][curInt = 0] = 0;
  89.     dataII[1][0] = 0;
  90.     dataII[2][0] = 0;
  91.     for (x = 0; x <  height; x++) {
  92.         for (y = 0; y < width; y++) {
  93.             if (!shift) {
  94.                 dataII[0][curInt] = 0;
  95.                 dataII[1][curInt] = 0;
  96.                 dataII[2][curInt] = 0;
  97.             }
  98.             c[0] = [self getIntFrom: myStream];
  99.             c[1] = [self getIntFrom: myStream];
  100.             c[2] = [self getIntFrom: myStream];
  101.             c[0] = c[0] << (iwid - bits);
  102.             c[1] = c[1] << (iwid - bits);
  103.             c[2] = c[2] << (iwid - bits);
  104.             if (NXAtEOS(myStream)) return NO;
  105.             if (shift + bits == iwid) {
  106.                 dataII[0][curInt]     |= (c[0] >> shift);
  107.                 dataII[1][curInt]     |= (c[1] >> shift);
  108.                 dataII[2][curInt]     |= (c[2] >> shift);
  109.                 curInt++;
  110.                 shift = 0;
  111.             }
  112.             else if (shift + bits > iwid) {
  113.                 dataII[0][curInt]         |= (c[0] >> shift);
  114.                 dataII[1][curInt]         |= (c[1] >> shift);
  115.                 dataII[2][curInt++]     |= (c[2] >> shift);
  116.                 shift = shift + bits - iwid;
  117.                 dataII[0][curInt] = c[0] << (bits - shift);
  118.                 dataII[1][curInt] = c[1] << (bits - shift);
  119.                 dataII[2][curInt] = c[2] << (bits - shift);
  120.             }
  121.             else {
  122.                 dataII[0][curInt] |= (c[0] >> shift);
  123.                 dataII[1][curInt] |= (c[1] >> shift);
  124.                 dataII[2][curInt] |= (c[2] >> shift);
  125.                 shift += bits;
  126.             }
  127.         }
  128.         shift += padBits;
  129.     }
  130.  
  131.     return YES;
  132. }
  133.  
  134. - (BOOL)readCompressedFromStream
  135. {
  136.     int                x, y, shift, curByte;
  137.     unsigned char        c[3];
  138.  
  139. #ifdef DEBUG
  140.     fprintf(stderr, "Okay, we're off and reading condensed data\n");
  141. #endif
  142.  
  143.     [self killToEOL];
  144.  
  145.     shift = 0;
  146.     data[0][curByte = 0] = 0;
  147.     data[1][0] = 0;
  148.     data[2][0] = 0;
  149.     for (x = 0; x < height; x++) {
  150.         for (y = 0; y < width; y++) {
  151.             c[0] = NXGetc(myStream) << cwid - bits;
  152.             c[1] = NXGetc(myStream) << cwid - bits;
  153.             c[2] = NXGetc(myStream) << cwid - bits;
  154.             if (NXAtEOS(myStream)) return NO;
  155.             if (shift + bits == cwid) {
  156.                 data[0][curByte]         |= (c[0] >> shift);
  157.                 data[1][curByte]         |= (c[1] >> shift);
  158.                 data[2][curByte++]     |= (c[2] >> shift);
  159.                 shift = 0;
  160.                 data[0][curByte] = 0;
  161.                 data[1][curByte] = 0;
  162.                 data[2][curByte] = 0;
  163.             }
  164.             else if (shift + bits > cwid) {
  165.                 data[0][curByte]         |= (c[0] >> shift);
  166.                 data[1][curByte]         |= (c[1] >> shift);
  167.                 data[2][curByte++]     |= (c[2] >> shift);
  168.                 shift = shift + bits - cwid;
  169.                 data[0][curByte] = c[0] << (bits - shift);
  170.                 data[1][curByte] = c[1] << (bits - shift);
  171.                 data[2][curByte] = c[2] << (bits - shift);
  172.             }
  173.             else {
  174.                 data[0][curByte] |= (c[0] >> shift);
  175.                 data[1][curByte] |= (c[1] >> shift);
  176.                 data[2][curByte] |= (c[2] >> shift);
  177.                 shift += bits;
  178.             }
  179.         }
  180.         shift += padBits;
  181.     }
  182.  
  183.     return YES;
  184. }
  185.  
  186. - readFromStream: (NXStream *)stream from: sender;
  187. {
  188.     id        image;
  189.  
  190. #ifdef DEBUG
  191.     fprintf(stderr, "Made it to read\n");
  192. #endif
  193.  
  194.     myStream = stream;
  195.  
  196.     [self getString: type from: myStream];
  197. #ifdef DEBUG
  198.     fprintf(stderr, "Type: %s\n", type);
  199. #endif
  200.     width = [self getIntFrom: myStream];
  201.     height = [self getIntFrom: myStream];
  202.     levels = [self getIntFrom: myStream];
  203.     bits = log(levels + 1) / log (2);
  204.     cwid = sizeof(unsigned char) * 8;
  205.     iwid = sizeof(unsigned int) * 8;
  206. #ifdef DEBUG
  207.     fprintf(stderr, "Type %s of dimensions %dx%d and levels %d or %d bits. intbits = %d, charbits = %d\n", type, width, height, levels + 1, bits, iwid, cwid);
  208. #endif
  209.  
  210.     image = [[NXBitmapImageRep alloc]     initDataPlanes: NULL
  211.                                         pixelsWide: width
  212.                                         pixelsHigh: height
  213.                                         bitsPerSample: bits
  214.                                         samplesPerPixel: 3
  215.                                         hasAlpha: NO
  216.                                         isPlanar: YES
  217.                                         colorSpace: NX_RGBColorSpace
  218.                                         bytesPerRow: 0
  219.                                         bitsPerPixel: 0];
  220.     if (!image) return nil;
  221.     [image getDataPlanes: data]; 
  222. #ifdef DEBUG
  223.     fprintf(stderr, "%p %p %p\n", data[0], data[1], data[2]);
  224. #endif
  225.  
  226.     padBits = [image bytesPerRow] * 8 - bits * width;
  227.  
  228.     if (!strcmp(type, "P3")) {
  229.         if (![self readRawFromStream]) {
  230.             [image free];
  231.             return nil;
  232.         }
  233.     }
  234.     else if (!strcmp(type, "P6")) {
  235.         if (![self readCompressedFromStream]) {
  236.             [image free];
  237.             return nil;
  238.         }
  239.     }
  240.     else return nil;
  241.     
  242.     return image;
  243. }
  244.  
  245. static BOOL WriteRaw(id image, NXStream *stream, id imageCon)
  246. {
  247.     int                    w = [image pixelsWide],
  248.                         h = [image pixelsHigh],
  249.                         length = w * h;
  250.     GetPixelNextFunc        myFunc;
  251.     Pixel                *pixel;
  252.     NXColorSpace        cs = [image colorSpace];
  253.     NXColor                tColor;
  254.     float                    maxColor = pow(2, (float)[image bitsPerSample]) - 1.0;
  255.     int                    x, y;
  256.  
  257.     NXPrintf(stream, "P3\n");
  258.     NXPrintf(stream, "%d %d\n", w, h);
  259.     NXPrintf(stream, "%d\n", (int)maxColor);
  260.     [imageCon resetNext];
  261.     myFunc = [imageCon getNextFunction];
  262.     for (x = y = 0; x < length; x++, y++) {
  263.         pixel = myFunc();
  264.         if (cs == NX_OneIsBlackColorSpace) {
  265.             NXPrintf(stream, "%d ", 1 - pixel->values[0]);
  266.             NXPrintf(stream, "%d ", 1 - pixel->values[0]);
  267.             NXPrintf(stream, "%d ", 1 - pixel->values[0]);
  268.         } else if (cs == NX_OneIsWhiteColorSpace) {
  269.             NXPrintf(stream, "%d ", pixel->values[0]);
  270.             NXPrintf(stream, "%d ", pixel->values[0]);
  271.             NXPrintf(stream, "%d ", pixel->values[0]);
  272.         } else if (cs == NX_RGBColorSpace) {
  273.             NXPrintf(stream, "%d ", pixel->values[0]);
  274.             NXPrintf(stream, "%d ", pixel->values[1]);
  275.             NXPrintf(stream, "%d ", pixel->values[2]);
  276.         } else if (cs == NX_CMYKColorSpace) {
  277.             tColor = NXConvertCMYKToColor(
  278.                                 (float)pixel->values[0] / maxColor,
  279.                                 (float)pixel->values[1] / maxColor,
  280.                                 (float)pixel->values[2] / maxColor,
  281.                                 (float)pixel->values[3] / maxColor);
  282.             NXPrintf(stream, "%d ", NXRedComponent(tColor) * maxColor);
  283.             NXPrintf(stream, "%d ", NXGreenComponent(tColor) * maxColor);
  284.             NXPrintf(stream, "%d ", NXBlueComponent(tColor) * maxColor);
  285.         }
  286.         if (y == 6) {
  287.             y = 0;
  288.             NXPrintf(stream, "\n");
  289.         }
  290.     }
  291.  
  292.     return YES;
  293. }
  294.  
  295. static BOOL WriteCompact(id image, NXStream *stream, id imageCon)
  296. {
  297.     int                    w = [image pixelsWide],
  298.                         h = [image pixelsHigh],
  299.                         length = w * h;
  300.     GetPixelNextFunc        myFunc;
  301.     Pixel                *pixel;
  302.     NXColorSpace        cs = [image colorSpace];
  303.     NXColor                tColor;
  304.     float                    maxColor = pow(2, (float)[image bitsPerSample]) - 1.0;
  305.     int                    x;
  306.  
  307.     NXPrintf(stream, "P6\n");
  308.     NXPrintf(stream, "%d %d\n", w, h);
  309.     NXPrintf(stream, "%d\n", (int)maxColor);
  310.     [imageCon resetNext];
  311.     myFunc = [imageCon getNextFunction];
  312.     for (x = 0; x < length; x++) {
  313.         pixel = myFunc();
  314.         if (cs == NX_OneIsBlackColorSpace) {
  315.             NXPutc(stream, 1 - pixel->values[0]);
  316.             NXPutc(stream, 1 - pixel->values[0]);
  317.             NXPutc(stream, 1 - pixel->values[0]);
  318.         } else if (cs == NX_OneIsWhiteColorSpace) {
  319.             NXPutc(stream, pixel->values[0]);
  320.             NXPutc(stream, pixel->values[0]);
  321.             NXPutc(stream, pixel->values[0]);
  322.         } else if (cs == NX_RGBColorSpace) {
  323.             NXPutc(stream, pixel->values[0]);
  324.             NXPutc(stream, pixel->values[1]);
  325.             NXPutc(stream, pixel->values[2]);
  326. //            fprintf(stderr, "%3d %3d %3d...", pixel->values[0], pixel->values[1], pixel->values[2]);
  327.         } else if (cs == NX_CMYKColorSpace) {
  328.             tColor = NXConvertCMYKToColor(
  329.                                 (float)pixel->values[0] / maxColor,
  330.                                 (float)pixel->values[1] / maxColor,
  331.                                 (float)pixel->values[2] / maxColor,
  332.                                 (float)pixel->values[3] / maxColor);
  333.             NXPutc(stream, NXRedComponent(tColor) * maxColor);
  334.             NXPutc(stream, NXGreenComponent(tColor) * maxColor);
  335.             NXPutc(stream, NXBlueComponent(tColor) * maxColor);
  336.         }
  337.     }
  338.  
  339.     return YES;
  340. }
  341.  
  342. - (BOOL)write: (id)image toStream: (NXStream *)stream from: sender;
  343. {
  344.     id        imageCon = [sender getImageControl: image];
  345.  
  346.     if ([image bitsPerSample] > 8) {
  347.         return WriteRaw(image, stream, imageCon);
  348.     } else {
  349.         return WriteCompact(image, stream, imageCon);
  350.     }
  351. }
  352.  
  353. - readAllFromStream: (NXStream *)stream from: sender
  354. {
  355.     return nil;
  356. }
  357.  
  358. - (BOOL)writeAll: (id)image toStream: (NXStream *)stream
  359. {
  360.     return NO;
  361. }
  362.  
  363. - customSaveView: (int)width
  364. {
  365.     return nil;
  366. }
  367.  
  368. - customOpenView: (int)width
  369. {
  370.     return nil;
  371. }
  372.  
  373. - (char *)getFormatName
  374. {
  375.     return("Portable Pixmap (PPM)");
  376. }
  377.  
  378.  - (BOOL)setCustomParameter: (const char *)parameter withValue: (void *)ptr
  379. {
  380.     return NO;
  381. }
  382.  
  383.  - (void *)getCustomParameter: (const char *)parameter
  384. {
  385.     return nil;
  386. }
  387.  
  388. - (char *)copyrightNotice
  389. {
  390.     return "PPM Converter\nby Alex Raftis\nCopyright (c) 1991 Cal Poly State University\nEmail bugs to alex@data.ACS.CalPoly.EDU";
  391. }
  392.  
  393. - (int)errorState
  394. {
  395.     return CONVERT_ERR_NONE;
  396. }
  397.  
  398. - (int)errorMessage
  399. {
  400.     return ERROR_NO_ERROR;
  401. }
  402.  
  403. - (char *)errorStringMessage
  404. {
  405.     return NULL;
  406. }
  407.  
  408. - (BOOL)needsWindowServer;
  409. {
  410.     return NO;
  411. }
  412.  
  413. - (char *)protocolVersion
  414. {
  415.     return "1.0";
  416. }
  417.  
  418. @end
  419.